//
//  ILGRuntimeModule.m
//  ILGDemo
//
//  Created by happy on 2020/3/22.
//  Copyright © 2020 Happy. All rights reserved.
//

#import "ILGRuntimeModule.h"

@implementation ILGRuntimeModule

- (void)performTestMethod
{
    ILGRuntimeModule *testModel = [[ILGRuntimeModule alloc] init];
//    [testModel setValue:@"Failure" forKey:@"result"];
//    NSString *valueResult = [testModel valueForKey:@"result"];

    [testModel performSelector:@selector(setResult:) withObject:@"Failure"];
    NSString *valueResult = [testModel performSelector:@selector(result)];
        
    //    NSDictionary *dic = @{@"feeling":@"挺好的",@"name":@"ZhangSan",@"country":@"China", @"className":@"ILGBaseModel"};
    //    ILGTestModel *model = [ILGTestModel modelWithDictionary:dic];
        
    //    NSString *path = [ILGLocalData filePathFromDocuments:@"model"];
    //    [ILGLocalData archiverSave:model path:path];
    //
    //    ILGTestModel *modelTmp = [ILGLocalData unarchiveObject:path];
    //    ILGTestModel *model4 = [model mutableCopy];
}

inline void ilg_exchangeImplementations(Class theClass, SEL originalSeletor, SEL swizzleSelector) {
    Method originalMethod = class_getInstanceMethod(theClass, originalSeletor);
    Method swizzledMethod = class_getInstanceMethod(theClass, swizzleSelector);
    method_exchangeImplementations(originalMethod, swizzledMethod);
}


#pragma mark - NSObject

- (void)doesNotRecognizeSelector:(SEL)aSelector {
    [super doesNotRecognizeSelector:aSelector];
    
}

void setResult(id targetClass ,SEL _cmd, NSString *value)
{
    objc_setAssociatedObject(targetClass, "meetingResult", value, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

NSString* result(id targetClass ,SEL _cmd)
{
    return objc_getAssociatedObject(targetClass, "meetingResult");
}

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if (sel == NSSelectorFromString(@"setResult:")) {
        class_addMethod([self class], sel, (IMP)setResult, "v@:@");
        return NO;
    } else if (sel == NSSelectorFromString(@"result")) {
        class_addMethod([self class], sel, (IMP)result, "@@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

- (id)forwardingTargetForSelector:(SEL)aSelector {
    if (aSelector == @selector(foo)) {
//        return [ILGPerson new];
    }
    return [super forwardingTargetForSelector:aSelector];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    if ([NSStringFromSelector(aSelector) isEqualToString:@"foo"]) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    return [super methodSignatureForSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
    SEL sel = anInvocation.selector;

//    ILGPerson *person = [ILGPerson new];
//    if ([person respondsToSelector:sel]) {
//        [anInvocation invokeWithTarget:person];
//    } else {
//        [self doesNotRecognizeSelector:sel];
//    }
}


#pragma mark - other

- (void)foo {
    
}

void fooMethod(id obj, SEL _cmd) {
    NSLog(@"Doing fooMethod");//新的foo函数
}

+ (void)callMethodCoveredByCategory:(id)object methodName:(NSString *)methodName
{
    unsigned count;
    Method *methods = class_copyMethodList([object class], &count);
    int index = -1;
    for (int i = 0; i < count; i++) {
        SEL name = method_getName(methods[i]);
        NSString *strName = [NSString stringWithCString:sel_getName(name) encoding:NSUTF8StringEncoding];
        NSLog(@"strName = %@", strName);
        if ([strName isEqualToString:methodName]) {
            index = i;
        }
    }
    
    if (index == -1) {
        free(methods);

        Class class = objc_getMetaClass(object_getClassName([object class]));
        methods = class_copyMethodList(class, &count);
        for (int i = 0; i < count; i++) {
            SEL name = method_getName(methods[i]);
            NSString *strName = [NSString stringWithCString:sel_getName(name) encoding:NSUTF8StringEncoding];
            NSLog(@"strName = %@", strName);
            if ([strName isEqualToString:methodName]) {
                index = i;
            }
        }
    }
   
    
    if (index > 0) {
        SEL sel = method_getName(methods[index]);
        IMP imp = method_getImplementation(methods[index]);
        ((void (*)(id, SEL))imp)(object,sel);
    }
    
    free(methods);
}

@end
